package com.kawins.supers.message.socket.manager;

import com.kawins.base.share.BaseConstant;
import com.kawins.supers.message.socket.HandlerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.PongMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import java.io.Serializable;

/**
 * @author rankai
 *         createTime 2017-10-2017/10/30 14:40
 */
public class IWebSocketHandler extends TextWebSocketHandler {

    private static final Logger log = LoggerFactory.getLogger(IWebSocketHandler.class);

    private HandlerService handlerService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.debug("webSocketSession id {} connection opened", session.getId());
        Serializable buildKey = buildKey(session);
        if (buildKey != null) {
            if (handlerService != null) {
                handlerService.opened(buildKey);
            }
            Object sessionId = session.getAttributes()
                    .get(HttpSessionHandshakeInterceptor.HTTP_SESSION_ID_ATTR_NAME);
            WebSocketBank.put(buildKey, (Serializable) sessionId, session);
            super.afterConnectionEstablished(session);
        } else {
            log.debug("webSocketSession id {} buildKey is null", session.getId());
            session.close();
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        if (handlerService != null) {
            handlerService.handleTextMsg(buildKey(session), message);
        }
        super.handleTextMessage(session, message);
    }

    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
        if (handlerService != null) {
            handlerService.handlePongMsg(buildKey(session), message);
        }
        super.handlePongMessage(session, message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("webSocketSession id {} error, message {}", session.getId(), exception.getMessage());
        Serializable buildKey = buildKey(session);
        if (buildKey != null) {
            if (handlerService != null) {
                handlerService.error(buildKey);
            }
            Object sessionId = session.getAttributes()
                    .get(HttpSessionHandshakeInterceptor.HTTP_SESSION_ID_ATTR_NAME);
            WebSocketBank.remove(buildKey, (Serializable) sessionId);
            super.handleTransportError(session, exception);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.debug("webSocketSession id {} connection closed", session.getId());
        Serializable buildKey = buildKey(session);
        if (buildKey != null) {
            if (handlerService != null) {
                handlerService.closed(buildKey);
            }
            Object sessionId = session.getAttributes()
                    .get(HttpSessionHandshakeInterceptor.HTTP_SESSION_ID_ATTR_NAME);
            WebSocketBank.remove(buildKey, (Serializable) sessionId);
            super.afterConnectionClosed(session, status);
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return super.supportsPartialMessages();
    }

    /**
     * @param session
     * @return
     */
    protected Serializable buildKey(WebSocketSession session) {
        Object object = session.getAttributes().get(BaseConstant.USER_ID_SESSION_KEY);
        if (object != null) {
            return (Serializable) object;
        }
        log.info("webSocketSession id {} buildKey is null");
        return null;

    }

    public void setHandlerService(HandlerService handlerService) {
        this.handlerService = handlerService;
    }
}
